import pygame
import time
import threading
from enum import Enum
from .board import Board
from .player import Player
from .game_mode import GameMode, RobotDifficulty
from .robot import Robot


class GameState(Enum):
    PLAYING = 1
    BLACK_WIN = 2
    WHITE_WIN = 3
    ROBOT_THINKING = 4


class Game:
    def __init__(self, game_mode=GameMode.PVP, robot_difficulty=RobotDifficulty.MEDIUM):
        self.board = Board()
        self.current_player = Player.BLACK
        self.state = GameState.PLAYING
        self.game_mode = game_mode
        self.robot_difficulty = robot_difficulty
        self.robot = Robot(robot_difficulty) if game_mode == GameMode.PVC else None
        self.robot_thinking_start_time = None
        self.robot_move_thread = None
        self.robot_move_result = None
        self.robot_move_error = None
        self.robot_task_id = 0

    def handle_click(self, row, col):
        if self.state != GameState.PLAYING:
            return False

        # 人机对战时，只允许玩家（黑子）下棋
        if self.game_mode == GameMode.PVC and self.current_player != Player.BLACK:
            return False

        if self.board.place_stone(row, col, self.current_player.value):
            if self.board.check_winner(row, col):
                if self.current_player == Player.BLACK:
                    self.state = GameState.BLACK_WIN
                else:
                    self.state = GameState.WHITE_WIN
            else:
                self.current_player = self.current_player.other()
                # 人机对战时，轮到机器人下棋
                if self.game_mode == GameMode.PVC and self.current_player == Player.WHITE:
                    self._trigger_robot_move()
            return True

        return False

    def _trigger_robot_move(self):
        # 让机器人开始下棋
        if not self.robot:
            return

        self.robot_task_id += 1
        task_id = self.robot_task_id
        self.robot_move_result = None
        self.robot_move_error = None
        self.state = GameState.ROBOT_THINKING
        self.robot_thinking_start_time = time.time()
        board_snapshot = self.board.clone()

        def compute_move(current_task_id, snapshot):
            try:
                move = self.robot.get_best_move(snapshot)
                if self.robot_task_id == current_task_id:
                    self.robot_move_result = move
                    self.robot_move_error = None
            except Exception as exc:
                if self.robot_task_id == current_task_id:
                    self.robot_move_result = None
                    self.robot_move_error = exc

        self.robot_move_thread = threading.Thread(
            target=compute_move,
            args=(task_id, board_snapshot),
            daemon=True
        )
        self.robot_move_thread.start()

    def update(self):
        # 处理机器人下棋逻辑
        if self.state == GameState.ROBOT_THINKING:
            elapsed = time.time() - self.robot_thinking_start_time if self.robot_thinking_start_time else 0
            move_ready = self.robot_move_result is not None
            error_ready = self.robot_move_error is not None
            thread_finished = self.robot_move_thread and not self.robot_move_thread.is_alive()
            if (move_ready or error_ready or thread_finished) and elapsed >= 0.5:
                move = None
                if move_ready and self.robot_move_result:
                    potential = self.robot_move_result
                    if isinstance(potential, tuple) and len(potential) == 2 and self.board.is_valid_move(*potential):
                        move = potential

                if not move:
                    fallback_robot = Robot(RobotDifficulty.HARD)
                    move = fallback_robot.get_best_move(self.board.clone())

                self.robot_move_thread = None
                self.robot_move_result = None
                self.robot_move_error = None
                self.robot_thinking_start_time = None

                if move and self.board.is_valid_move(*move):
                    row, col = move
                    if self.board.place_stone(row, col, Player.WHITE.value):
                        if self.board.check_winner(row, col):
                            self.state = GameState.WHITE_WIN
                        else:
                            self.state = GameState.PLAYING
                            self.current_player = Player.BLACK
                        return

                # 如果回退仍失败，则重置为玩家回合，避免卡死
                self.state = GameState.PLAYING
                self.current_player = Player.BLACK

    def undo(self):
        if self.state != GameState.PLAYING and self.state != GameState.ROBOT_THINKING:
            return False

        self._cancel_robot_task()

        # 人机对战时，需要撤销两步（玩家和机器人的棋子）
        if self.game_mode == GameMode.PVC:
            # 先撤销机器人的棋子
            if self.board.undo():
                # 再撤销玩家的棋子
                if self.board.undo():
                    self.current_player = Player.BLACK
                    self.state = GameState.PLAYING
                    return True
                else:
                    # 如果只能撤销一步，说明只有玩家下了一子
                    self.current_player = Player.BLACK
                    self.state = GameState.PLAYING
                    return True
        else:
            # 人人对战
            if self.board.undo():
                self.current_player = self.current_player.other()
                self.state = GameState.PLAYING
                return True

        return False

    def reset(self):
        self._cancel_robot_task()
        self.board.reset()
        self.current_player = Player.BLACK
        self.state = GameState.PLAYING
        self.robot_thinking_start_time = None

    def set_mode(self, game_mode, robot_difficulty=RobotDifficulty.MEDIUM):
        # 设置游戏模式
        self.game_mode = game_mode
        self.robot_difficulty = robot_difficulty
        self.robot = Robot(robot_difficulty) if game_mode == GameMode.PVC else None
        self.reset()

    def get_winner(self):
        if self.state == GameState.BLACK_WIN:
            return Player.BLACK
        elif self.state == GameState.WHITE_WIN:
            return Player.WHITE
        return None

    def _cancel_robot_task(self):
        # 停止机器人思考
        self.robot_task_id += 1
        self.robot_move_thread = None
        self.robot_move_result = None
        self.robot_move_error = None
        self.robot_thinking_start_time = None
